﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Linq;
using System.Windows.Forms;
using DevExpress.Skins;
using DevExpress.LookAndFeel;
using DevExpress.UserSkins;
using DevExpress.XtraEditors;
using DevExpress.XtraCharts;

namespace JobShop
{
    public partial class frmSolution : XtraForm
    {
        private TcGapReduction Algorithm { get; set; }
        
        public frmSolution(TcGapReduction prmAlgorithm)
        {
            Algorithm = prmAlgorithm;
            InitializeComponent();
            InitializeData();
            InitializeCharts();
        }
        //------------------------------------------------------------------------------

        private void InitializeData()
        {
            Algorithm.ProgressChanged += OnSchedulerWorkProgressed;
            Algorithm.RunWorkerCompleted += OnSchedulerWorkCompleted;
        }
        //------------------------------------------------------------------------------

        private void InitializeCharts()
        {
            chartSolution.AppearanceName = "Light";
            chartSolution.PaletteName = "Concourse";
            chartSolution.Legend.Visible = true;
        }
        //------------------------------------------------------------------------------

        private void OnSchedulerWorkProgressed(object sender, ProgressChangedEventArgs e)
        {
            if (IsDisposed || !Visible)
                return;

            if (InvokeRequired)
            {
                BeginInvoke((MethodInvoker)delegate() { OnSchedulerWorkProgressed(sender, e); });
                return;
            }

            UpdateViews();
        }
        //------------------------------------------------------------------------------

        private void OnSchedulerWorkCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (IsDisposed || !Visible)
                return;

            if (InvokeRequired)
            {
                BeginInvoke((MethodInvoker)delegate() { OnSchedulerWorkCompleted(sender, e); });
                return;
            }

            Text += " (Completed)";
        }
        //------------------------------------------------------------------------------

        private void UpdateSolutionView(TcSolution prmSolution)
        {
            Int32 m = prmSolution.Row;
            Int32 n = prmSolution.Column / 6;
            Int32[,] solution = prmSolution.Solution;
            Series[] collection = Enumerable.Range(0, n).Aggregate(new List<Series>(), (r, i) =>
            {
                Series series = new Series(String.Format("Job {0}", i + 1), ViewType.Gantt);
                series.Label.Visible = true;
                r.Add(series);
                return r;
            }).ToArray();

            Double[] offsets = Enumerable.Repeat<Double>(0.0f, m).ToArray();
            for (int i = 0; i < n; i++)
            {
                for (int j = 0; j < m; j++)
                {
                    offsets[j] += solution[j, i * 6 + 2] - solution[j, i * 6 + 1];
                    Int32 job = Convert.ToInt32(solution[j, i * 6 + 3]);
                    collection[job].Points.Add(new SeriesPoint((j + 1) * 10, new double[] { offsets[j], offsets[j] + solution[j, i * 6 + 5] - solution[j, i * 6 + 4] }));
                    offsets[j] += solution[j, i * 6 + 5] - solution[j, i * 6 + 4];
                }
            }

            // Add series collection to the chart.
            chartSolution.Series.BeginUpdate();
            chartSolution.Series.Clear();
            chartSolution.Series.AddRange(collection);
            chartSolution.Series.EndUpdate();
        }
        //------------------------------------------------------------------------------

        private void UpdateMakespanView(TcStatistics prmStat)
        {
            Func<String, IEnumerable<Double>, Series> GetSeries = delegate(String prmName, IEnumerable<Double> prmSeries)
                {
                    Series series = new Series(prmName, ViewType.Line);
                    series.Label.Visible = true;
                    for (Int32 i = 0; i < prmSeries.Count(); i++)
                        series.Points.Add(new SeriesPoint(i + 1, prmSeries.ElementAt(i)));
                    return series;
                };
            
            chartMakespan.Series.BeginUpdate();
            chartMakespan.Series.Clear();
            chartMakespan.Series.AddRange(new Series[4] { GetSeries("Best", prmStat.Bests), GetSeries("Worst", prmStat.Worsts), GetSeries("Avg", prmStat.Avgs), GetSeries("Med", prmStat.Medians) });
            chartMakespan.Series.EndUpdate();
        }
        //------------------------------------------------------------------------------

        private void UpdateViews()
        {
            if (Algorithm.Statistics != null)
            {
                UpdateSolutionView(Algorithm.Statistics.BestSolution);
                UpdateMakespanView(Algorithm.Statistics);
                proProgress.EditValue = Algorithm.Progress;
            }
        }
        //------------------------------------------------------------------------------
        
        private void frmMain_Load(object sender, EventArgs e)
        {
            UpdateViews();
        }
        //------------------------------------------------------------------------------

    }
    //------------------------------------------------------------------------------

}
//------------------------------------------------------------------------------